package org.neowei.image.filter;

import org.neowei.image.api.ImageOption;

final public class Filter {
	final public static double getRedValue(int rgbValue, double valueRed, double contributor) {
		int temp = rgbValue & 0x00ff0000;
		return valueRed + (temp >> 16) * contributor;
	}

	final public static double getGreenValue(int rgbValue, double valueGreen, double contributor) {
		int temp = rgbValue & 0x0000ff00;
		return valueGreen + (temp >> 8) * contributor;
	}

	final public static double getBlueValue(int rgbValue, double valueBlue, double contributor) {
		int temp = rgbValue & 0x000000ff;
		return valueBlue + temp * contributor;
	}

	final public static int comRGB(int redValue, int greenValue, int blueValue) {
		return (redValue << 16) + (greenValue << 8) + blueValue;
	}

	final public static int clip(int x) {
		if (x < 0)
			return 0;
		else if (x > 255)
			return 255;
		else
			return x;
	}

	final public static double getLanczos(int i, double inWidth, double outWidth) {
		double x = i * outWidth / inWidth;
		return Math.sin(x * StrictMath.PI) / (x * StrictMath.PI) * Math.sin(x * StrictMath.PI / 3) / (x * StrictMath.PI / 3);
	}

	final public static FilterOption getContrib(double neowidth, double srcwidth) {
		int numberHalfdots = (int) (srcwidth * 3 / neowidth);
		int numberdots = numberHalfdots * 2 + 1;
		double[] contrib = new double[numberdots], normContrib = new double[numberdots];
		contrib[numberHalfdots] = 1;
		double weight = 0.0;
		int i;
		for (i = 1; i <= numberHalfdots; i++) {
			contrib[numberHalfdots + i] = getLanczos(i, srcwidth, neowidth);
			weight += contrib[numberHalfdots + i];
		}
		for (i = numberHalfdots - 1; i >= 0; i--) {
			contrib[i] = contrib[numberHalfdots * 2 - i];
		}
		weight = weight * 2 + 1.0;
		for (i = 0; i <= numberHalfdots; i++) {
			normContrib[i] = (double) (contrib[i] / weight);
		}

		for (i = numberHalfdots + 1; i < numberdots; i++) {
			normContrib[i] = normContrib[numberHalfdots * 2 - i];
		}
		return new FilterOption(normContrib, numberHalfdots);
	}

	final public static int[] getWaterXY(ImageOption imageOption, int waterwidth, int waterheight) {
		int waterX = 0;
		int waterY = 0;
		int neowidth = imageOption.getNeowidth();
		int neoheight = imageOption.getNeoheight();
		int srcwidth = imageOption.getSrcwidth();
		int srcheight = imageOption.getSrcheight();
		int finalwidth;
		int finalheight;
		if (neowidth > 0 && neoheight > 0) {
			finalwidth = neowidth;
			finalheight = neoheight;
		} else {
			finalwidth = srcwidth;
			finalheight = srcheight;
		}
		if (finalwidth < waterwidth || finalheight < waterheight) {
			return new int[] { -1, -1 };
		}
		switch (imageOption.getWaterposition().toLowerCase()) {
		case "west":
			waterX = finalwidth - waterwidth;
			waterY = (finalheight - waterheight) / 2;
			break;
		case "east":
			waterY = (finalheight - waterheight) / 2;
			break;
		case "center":
			waterX = (finalwidth - waterwidth) / 2;
			waterY = (finalheight - waterheight) / 2;
			break;
		case "north":
			waterX = (finalwidth - waterwidth) / 2;
			break;
		case "south":
			waterX = (finalwidth - waterwidth) / 2;
			waterY = finalheight - waterheight;
			break;
		case "northwest":
			waterX = finalwidth - waterwidth;
			break;
		case "northeast":
			break;
		case "southwest":
			waterX = finalwidth - waterwidth;
			waterY = finalheight - waterheight;
			break;
		case "southeast":
			waterY = finalheight - waterheight;
			break;
		default:
			waterX = -1;
			waterY = -1;
			break;
		}
		return new int[] { waterX, waterY };
	}
}
